// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://kpdus.tripod.com/jad.html
// Decompiler options: packimports(3)
package br.unb.graphics.qos;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
import java.util.HashMap;
import java.util.ResourceBundle;

import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.labels.XYToolTipGenerator;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.Hour;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.Minute;
import org.jfree.data.time.Second;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;

import br.unb.graphics.InterfaceFactory;
import br.unb.utils.Resource;

import cgl.narada.sync.SyncTimestamp;

public class QosChart extends JPanel {
    //TODO Constants, (move to another file)

    private static final String WINDOW_LABEL = "windowSizeLabel";
    private static final String MS_LABEL = "msLabel";
    private static final String TIME_LABEL = "timeLabel";
    private String title;
    private JPanel windowPanel;
    private JLabel windowLabel;
    private ValueAxis valueaxis;
    private HashMap timeSeriesList;
    private XYLineAndShapeRenderer renderer;
    private ChartPanel chartpanel;
    private TimeSeriesCollection timeSeriesCollection;
    private static final ResourceBundle resources = Resource.QosChart;
    private static final InterfaceFactory ifactory = new InterfaceFactory(resources);

    public QosChart(String title) {

        super(new BorderLayout());

        this.title = title;
        timeSeriesList = new HashMap();
        timeSeriesCollection = new TimeSeriesCollection();
        chartpanel = new ChartPanel(createChart(timeSeriesCollection));
        chartpanel.setPreferredSize(new Dimension(500, 250));
        this.changePopupMenu(chartpanel.getPopupMenu());

        windowLabel = new JLabel();
        setWindowLabel(0);
        windowPanel = new JPanel(new BorderLayout());
        windowPanel.add(windowLabel, BorderLayout.EAST);
        windowPanel.setPreferredSize(new Dimension(500, 20));

        add(chartpanel, BorderLayout.CENTER);
        add(this.windowPanel, BorderLayout.SOUTH);
    }

    public void setWindowLabel(long window) {
        if (window > 0) {
            windowLabel.setText(
                    ifactory.getResourceString(WINDOW_LABEL) 
                    + window
                    + ifactory.getResourceString(MS_LABEL));
        } else {
            windowLabel.setText(" ");
        }
    }

    /**
     * Adds a new traffic to the traffic panel with the graphics of the Qos parameter in use
     * @param trafficName
     */
    public void addTraffic(String trafficName) {
        TimeSeries serie = new TimeSeries(trafficName, Millisecond.class);
        timeSeriesCollection.addSeries(serie);
        timeSeriesList.put(trafficName, serie);
    }

    /**
     * Removes a traffic
     */
    public void removeTraffic(String trafficName) {
        timeSeriesCollection.removeSeries(((TimeSeries) timeSeriesList.get(trafficName)));
        timeSeriesList.remove(trafficName);
    }

    /**
     * Adds a value to the graffic of the qos in use for a choosen traffic
     * @param value Value to be added
     * @param trafficName name of the traffic that will receive this value
     */
    public void addValueToTraffic(double valueMillisecond, String trafficName) {
        Millisecond millisecond = new Millisecond(new Date(SyncTimestamp.getLogicTime() / 1000));
        ((TimeSeries) timeSeriesList.get(trafficName)).addOrUpdate(millisecond, valueMillisecond);
    }

    /**
     * Adds a QoS value to a choosen traffic in a given instant
     * This method mus be used only on the data read from a file
     * @param value Value to be added
     * @param instant Value of the instant to be added (in microseconds)
     * @param trafficName name of the traffic that will receive this value
     */
    public void addValueToTraffic(double valueMillisecond, long instant, String trafficName) {
        Millisecond millisecond = new Millisecond(new Date(instant / 1000));
        ((TimeSeries) timeSeriesList.get(trafficName)).addOrUpdate(millisecond, valueMillisecond);
    }

    private JFreeChart createChart(XYDataset xydataset) {
        JFreeChart jfreechart = ChartFactory.createTimeSeriesChart(
                ifactory.getResourceString(title), // title
                ifactory.getResourceString(TIME_LABEL), // x-axis label
                ifactory.getResourceString(title), // y-axis label
                xydataset, // data
                true, // create legend?
                true, // generate tooltips?
                false // generate URLs?
                );
        XYPlot xyplot = jfreechart.getXYPlot();
        XYItemRenderer r = xyplot.getRenderer();

        if (r instanceof XYLineAndShapeRenderer) {
            renderer = (XYLineAndShapeRenderer) r;
            renderer.setDefaultEntityRadius(1);
            renderer.setDefaultShapesVisible(true);
            renderer.setDefaultShapesFilled(false);
            renderer.setDefaultLinesVisible(true);
            renderer.setBaseToolTipGenerator(new XYToolTipGenerator() {

                public String generateToolTip(XYDataset dataset, int series, int item) {
                    Second second;
                    Minute minute;
                    Hour hour;
                    int segundo, minuto, hora;
                    long ms;
                    Millisecond millisecond = (Millisecond) ((timeSeriesCollection.getSeries(series)).getDataItem(item).getPeriod());
                    double value = (timeSeriesCollection.getSeries(series)).getDataItem(item).getValue().doubleValue();
                    second = millisecond.getSecond();
                    minute = second.getMinute();
                    hour = minute.getHour();

                    ms = millisecond.getMillisecond();
                    segundo = second.getSecond();
                    minuto = minute.getMinute();
                    hora = hour.getHour();
                    return "(" + hora + ":" + minuto + ":" + segundo + "." + ms + ", " + value + ")";
                }
            });
        }
        valueaxis = xyplot.getDomainAxis();
        valueaxis.setAutoRange(true);
        valueaxis = xyplot.getRangeAxis();
        valueaxis.centerRange(0);

        return jfreechart;
    }

    public void restart() {
        this.remove(chartpanel);
        timeSeriesCollection = new TimeSeriesCollection();
        chartpanel = new ChartPanel(createChart(timeSeriesCollection));
        chartpanel.setPreferredSize(new Dimension(500, 270));
        this.changePopupMenu(chartpanel.getPopupMenu());
        this.add(chartpanel);
    }

    private void changePopupMenu(JPopupMenu popup) {

        final JMenuItem mLines = new JMenuItem("Hide Lines");
        mLines.addActionListener(
                //TODO review actionListener implementation
                new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                if (renderer.getDefaultLinesVisible()) {
                    mLines.setText("Show Lines");
                    renderer.setDefaultLinesVisible(false);
                } else {
                    mLines.setText("Hide Lines");
                    renderer.setDefaultLinesVisible(true);
                }
            }
        });

        final JMenuItem mShapes = new JMenuItem("Hide Shapes");
        mShapes.addActionListener(
                //TODO review actionListener implementation
                new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                if (renderer.getDefaultShapesVisible()) {
                    mShapes.setText("Show Shapes");
                    renderer.setDefaultShapesVisible(false);
                } else {
                    mShapes.setText("Hide Shapes");
                    renderer.setDefaultShapesVisible(true);
                }
            }
        });

        final JMenuItem mWindow = new JMenuItem("Window Size...");
        mWindow.addActionListener(
                //TODO review actionListener implementation
                new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                String windowString = JOptionPane.showInputDialog(
                        Resource.getString("TIME_WINDOW_SIZE_TO_ESTIMATE_BANDWIDTH_AND_LOSS"));
                try {
                    int window = Integer.parseInt(windowString);
                    if (window > 0) {
                        setWindowLabel(window);
                        QoSController.getInstance().setWindowSize(window);
                    } else {
                        throw new NumberFormatException("");
                    }
                } catch (NumberFormatException nfe) {
                    //JOptionPane.showMessageDialog(null, "Valor da janela inválida");
                }
            }
        });
        popup.addSeparator();
        popup.add(mLines);
        popup.add(mShapes);

        popup.addSeparator();

        popup.add(mWindow);
    }
}
    
